/** m2settings is a GUI to configure Maven 2 settings.xml 
 * 
 *  Copyright (C) 2007 Regis Decamps <decamps@users.sf.net>
 * 
 *  This file is part of m2settings.
 *
 *  m2settings is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version. 
 *
 *  Foobar is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with Foobar; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *  or read it online http://www.gnu.org/licenses/gpl.txt
 *
 **/
package info.decamps.m2settings.documentation;

import com.sun.org.apache.xalan.internal.xsltc.dom.LoadDocument;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

/**
 * Provides documentation for Maven settings ased on the definition found in
 * <code>settings.xsd</code> .
 *
 * @author regis
 *
 */
public class DocumentationProvider {
    public static final String SETTINGS_XSD_URL = "http://maven.apache.org/maven-v4_0_0.xsd";
    private Map<String, String> descriptions;
    /* singleton */
    private static DocumentationProvider documentation=null;
    
    /**
     * Default constructor creates documentation from settings-1.0.xsd
     */
    public DocumentationProvider() {
        descriptions=new HashMap();
        try {
            loadSettingsXSD(getClass().getResourceAsStream("/settings-1.0.xsd"));
            // no exception can be raised with embedded settings.xsd
        } catch (ParserConfigurationException ex) {
            ex.printStackTrace();
        } catch (SAXException ex) {
            ex.printStackTrace();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
    /**
     * Read a stream corresponding to the Settings XML Schema Definition.
     *
     * @param mavenSettingsXSDFile
     *            The stream that contains settings.xsd
     * @throws ParserConfigurationException
     * @throws SAXException
     * @throws IOException
     */
    private void loadSettingsXSD(InputStream mavenSettingsXSDFile)
    throws ParserConfigurationException, SAXException, IOException {
        DocumentBuilderFactory docFactory = DocumentBuilderFactory
                .newInstance();
        DocumentBuilder builder;
        builder = docFactory.newDocumentBuilder();
        Document settingsXSD = builder.parse(mavenSettingsXSDFile);
        readDescritptionInNodes(settingsXSD.getDocumentElement(), "/");
    }
    
    private void readDescritptionInNodes(Element xmlElement,
            String xmlElementName) {
        if ("xs:documentation".equals(xmlElement.getNodeName())
        && "description".equals(xmlElement.getAttribute("source"))) {
            addDescription(xmlElementName.substring(1), xmlElement
                    .getTextContent().replaceAll("\n|\r|\t|  ", ""));
        }
        NodeList children = xmlElement.getChildNodes();
        for (int i = 0; i < children.getLength(); i++) {
            if (children.item(i).getNodeType() == Node.ELEMENT_NODE) {
                // recursive function
                String nodeName = xmlElement.getAttribute("name");
                if (nodeName.length() > 0) {
                    nodeName = "/" + nodeName;
                }
                readDescritptionInNodes((Element) children.item(i),
                        xmlElementName + nodeName);
            }
        }
    }
    
    private void addDescription(String xmlPseudoPath,
            String documentationDescription) {
        descriptions.put(xmlPseudoPath, documentationDescription);
    }
    
    public InputStream jarget(String fileName) {
        return getClass().getResourceAsStream(fileName);
    }
    
    public String getDescription(String key) {
        return (String) descriptions.get(key);
        
    }

    public static DocumentationProvider getInstance() {
        if (documentation==null) {
            documentation=new DocumentationProvider();
            
        }        
        return documentation;
    }
}
